package org.dromara.sheet.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.dto.RoleDTO;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.sheet.constant.SplitType;
import org.dromara.sheet.domain.*;
import org.dromara.sheet.domain.dto.SysUserDto;
import org.dromara.sheet.domain.dto.platformList.*;
import org.dromara.sheet.domain.vo.*;
import org.dromara.sheet.enums.FieldShowTypeEnum;
import org.dromara.sheet.enums.SearchTypeEnum;
import org.dromara.sheet.enums.YesOrNoEnum;
import org.dromara.sheet.mapper.*;
import org.dromara.sheet.service.PlatformListService;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 平台列表通用服务实现
 * @author Ysl
 */
@RequiredArgsConstructor
@Service
public class PlatformListServiceImpl implements PlatformListService {

    private final PlatformListMapper platformListMapper;
    private final SysSheetButtonMapper sheetButtonMapper;
    private final SysSheetSearchMapper sheetSearchMapper;
    private final SysDataSourceMapper dataSourceMapper;
    private final SysSheetFieldMapper sheetFieldMapper;
    private final SysSheetMapper sheetMapper;
    private final SysSheetSelectMapper sheetSelectMapper;

    private final SysSheetButtonAuthMapper buttonAuthMapper;

    /**
     * 获取搜索和按钮配置
     * @param sheetId   应用ID
     * @return
     */
    @Override
    public SearchReturnDto getSearchAndButtonConfig(Long sheetId) {
        SearchReturnDto dto = new SearchReturnDto();
        // 获取按钮配置
        List<SearchButtonDto> buttonList = getSheetButtonConfig(sheetId);
        // 获取搜索配置
        List<SearchConfigDto> searchConfigList = getSearchConfigList(sheetId);

        dto.setButtonList(buttonList);
        dto.setSearchConfigList(searchConfigList);
        return dto;
    }

    /**
     * 获取平台通用列表数据
     * @param paramsDto     请求参数
     * @return
     */
    @Override
    public TableDataDto getListData(RequestParamsDto paramsDto) {
        TableDataDto dataDto = new TableDataDto();
        // 获取应用信息
        SysSheetVo sheet = sheetMapper.selectVoById(paramsDto.getSheetId());

        // 获取表头信息
        dataDto.setHeadList(getTableHeadData(paramsDto.getSheetId()));

        // 获取查询条件
        SearchParamsDto searchParams = getPlatformListSearchParams(paramsDto);

        // 获取列表数据
        String tableName = sheet.getTableName();
        String tableId = sheet.getTableId();

        // 获取查询字段
        List<SysSheetFieldVo> fieldList = sheetFieldMapper.selectVoList(
            new LambdaQueryWrapper<SysSheetField>().eq(SysSheetField::getSheetId, paramsDto.getSheetId())
                .eq(SysSheetField::getTableStatus, YesOrNoEnum.YES.getCode()).orderByAsc(SysSheetField::getTableSort)
        );
        String fieldName = fieldList.stream().map(SysSheetFieldVo::getFieldName).collect(Collectors.joining(",t."));
        if (StringUtils.isNotEmpty(fieldName)) {
            fieldName = "t."+fieldName;
        } else {
            throw new RuntimeException("请配置列表显示字段");
        }

        searchParams.setTableName(tableName);
        searchParams.setTableId(tableId);
        searchParams.setFieldName(fieldName);
        searchParams.setSheetId(paramsDto.getSheetId());

        // 查询数据
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNum(paramsDto.getPageNum());
        pageQuery.setPageSize(paramsDto.getPageSize());
        Page<Map<String, Object>> page = platformListMapper.getDataList(pageQuery.build(), searchParams);

        // 返回数据体
        List<Map<String, Object>> dataList = new ArrayList<>();

        // 获取数据下拉项值
        List<Object> tableIds = page.getRecords().stream().map(item -> item.get(tableId)).toList();
        List<SysSheetSelectVo> selectList;
        if (tableIds.size() > 0) {
            selectList = sheetSelectMapper.selectVoList(
                new LambdaQueryWrapper<SysSheetSelect>().in(SysSheetSelect::getOrderId, tableIds)
            );
        } else {
            selectList = new ArrayList<>();
        }

        // 获取下拉项字段
        List<SysSheetFieldVo> selectFieldList = fieldList.stream().filter(field -> FieldShowTypeEnum.getAllSelectType().contains(field.getShowType())).toList();

        // 获取图片字段
        List<SysSheetFieldVo> imgFieldList = fieldList.stream().filter(field -> field.getShowType().equals(17)).toList();
        List<DataOssDto> ossDtoList = new ArrayList<>();
        imgFieldList.forEach(item -> {
            page.getRecords().forEach(map -> {
                if (map.containsKey(item.getFieldName()) && map.get(item.getFieldName())!= null){
                    String ossId = map.get(item.getFieldName()).toString();
                    if (StringUtils.isNotEmpty(ossId)){
                        DataOssDto dto = new DataOssDto();
                        for (String id : ossId.split(SplitType.SPLIT_COMMA)) {
                            dto.setOrderId((Long) map.get(tableId));
                            dto.setOssId(id);
                            dto.setTenantId(LoginHelper.getTenantId());
                            dto.setFieldName(item.getFieldName());
                            ossDtoList.add(dto);
                        }
                    }
                }
            });

        });
        List<DataOssDto> ossUrlList = platformListMapper.getOSSUrl(ossDtoList);

        // 获取系统用户
        List<SysUserDto> userList = platformListMapper.getUserList();

        page.getRecords().forEach(map -> {
            Map<String,Object> dataMap = new HashMap<>();
            // 为下拉字段赋值
            for (SysSheetFieldVo field : selectFieldList) {
                if (map.containsKey(field.getFieldName())){
                    if (!selectList.isEmpty()){
                        SysSheetFieldVo fieldVo = fieldList.stream().filter(item -> item.getFieldName().equals(field.getFieldName())).findFirst().orElse(null);
                        if (fieldVo != null){
                            List<SysSheetSelectVo> list = selectList.stream().filter(item -> item.getOrderId().equals(map.get(tableId)) && item.getSheetId().equals(paramsDto.getSheetId())
                                && item.getFieldId().equals(fieldVo.getSheetFieldId())).toList();
                            String value = list.stream().map(SysSheetSelectVo::getName).collect(Collectors.joining(";"));
                            map.put(field.getFieldName(), value);
                        }
                    }
                }
            }
            // 图片字段赋值
            Map<Long, List<DataOssDto>> groupMap = ossUrlList.stream().collect(Collectors.groupingBy(DataOssDto::getOrderId));
            groupMap.forEach((key,value) -> {
                if (map.get(tableId).equals(key)){
                    String url = value.stream().map(DataOssDto::getOssUrl).collect(Collectors.joining(","));
                    DataOssDto dto = value.stream().filter(item -> item.getOrderId().equals(key)).findFirst().orElse(null);
                    if (dto != null){
                        map.put(dto.getFieldName(), url);
                    }
                }
            });
            // 设置创建人修改人
            map.forEach((key,value) ->{
                if (key.equals("create_by") || key.equals("update_by")){
                    SysUserDto sysUserDto = userList.stream().filter(item -> item.getUserId().equals(value)).findFirst().orElse(new SysUserDto());
                    map.put(key, sysUserDto.getNickName());
                }
            });
            map.forEach((key,value) ->{
                dataMap.put(StringUtils.toCamelCase(key), value);
            });
            dataList.add(dataMap);
        });
        dataDto.setDataList(dataList);
        dataDto.setTotal(page.getTotal());

        return dataDto;
    }

    /**
     * 获取列表按钮配置
     * @param bindId   绑定ID
     * @return
     */
    @Override
    public List<SearchButtonDto> getSheetButtonConfig(Long bindId) {
        List<SysSheetButtonVo> allButtonList = sheetButtonMapper.selectVoList(
            new LambdaQueryWrapper<SysSheetButton>().eq(SysSheetButton::getBindId, bindId)
                .eq(SysSheetButton::getStatus, YesOrNoEnum.YES.getCode()).orderByAsc(SysSheetButton::getSort)
        );

        List<SysSheetButtonVo> buttonList = new ArrayList<>();
        // 获取授权的按钮
        List<SysSheetButtonAuthVo> authList = new ArrayList<>();
        if (LoginHelper.isSuperAdmin()){
            buttonList = allButtonList;
        } else {
            List<RoleDTO> roles = LoginHelper.getLoginUser().getRoles();
            if (roles.size() > 0){
                authList = buttonAuthMapper.selectVoList(
                    new LambdaQueryWrapper<SysSheetButtonAuth>()
                        .eq(SysSheetButtonAuth::getBindId, bindId)
                        .in(SysSheetButtonAuth::getRoleId, roles.stream().map(RoleDTO::getRoleId).toList())
                );
            }
            List<SysSheetButtonAuthVo> finalAuthList = authList;
            buttonList = allButtonList.stream().filter(item -> finalAuthList.stream().map(SysSheetButtonAuthVo::getSheetButtonId).toList().contains(item.getSheetButtonId())).toList();
        }

        List<SysSheetButtonVo> noGroupList = buttonList.stream().filter(item ->  StringUtils.isEmpty(item.getShowGroup())).toList();
        Map<String, List<SysSheetButtonVo>> groupMap = buttonList.stream().filter(item -> StringUtils.isNotEmpty(item.getShowGroup())).collect(Collectors.groupingBy(SysSheetButtonVo::getShowGroup));

        List<SearchButtonDto> dtoList = new ArrayList<>();
        noGroupList.forEach(item -> {
            SearchButtonDto dto = JSONUtil.toBean(JSONUtil.toJsonStr(item), SearchButtonDto.class);
            dto.setType(0);
            dtoList.add(dto);
        });
        groupMap.forEach((key,value) -> {
            SearchButtonDto dto = new SearchButtonDto();
            dto.setShowName(key);
            dto.setShowArea(value.get(0).getShowArea());
            List<SearchButtonDto> groupList = new ArrayList<>();
            value.forEach(item -> {
                SearchButtonDto groupDto = JSONUtil.toBean(JSONUtil.toJsonStr(item), SearchButtonDto.class);
                groupList.add(groupDto);
            });
            dto.setType(1);
            dto.setGroupList(groupList);
            dtoList.add(dto);
        });

        return dtoList;
    }

    /**
     * 获取列表搜索配置
     * @param sheetId   应用ID
     * @return
     */
    @Override
    public List<SearchConfigDto> getSearchConfigList(Long sheetId) {
        List<SysSheetSearchVo> searchList = sheetSearchMapper.selectVoList(
            new LambdaQueryWrapper<SysSheetSearch>().eq(SysSheetSearch::getSheetId, sheetId)
                .eq(SysSheetSearch::getStatus, YesOrNoEnum.YES.getCode()).orderByAsc(SysSheetSearch::getSort)
        );
        List<SearchConfigDto> list = new ArrayList<>();
        searchList.forEach(item -> {
            SearchConfigDto dto = JSONUtil.toBean(JSONUtil.toJsonStr(item), SearchConfigDto.class);
            if (item.getDataSourceId() != null){
                List<SearchDataSourceDto> dataList = new ArrayList<>();
                if (item.getDataSourceType() == 1){
                    // 数据字典
                    dataList = sheetSearchMapper.getDictDataList(item.getDataSourceId());
                } else {
                    // 自定义数据源
                    SysDataSourceVo dataSource = dataSourceMapper.getDataSourceBySheetSourceId(item.getDataSourceId());
                    if (dataSource != null){
                        dataList = sheetSearchMapper.getDiyDataSourceList(dataSource);
                    }
                }
                dto.setDataSourceList(dataList);

                if (SearchTypeEnum.getTreeSelectType().contains(item.getSearchType())){
                    SearchDataSourceDto dataSourceDto = new SearchDataSourceDto();
                    List<SearchDataSourceDto> list1 = dataSourceDto.builTree(dataList);
                    dto.setDataSourceList(list1);
                }
            }
            list.add(dto);
        });

        return list;
    }

    /**
     * 获取表头数据
     * @param sheetId
     * @return
     */
    @Override
    public List<TableHeadDto> getTableHeadData(Long sheetId) {
        return sheetFieldMapper.getHeadList(sheetId);
    }

    /**
     * 获取平台通用列表搜索条件
     * @param paramsDto     请求参数
     * @return
     */
    @Override
    public SearchParamsDto getPlatformListSearchParams(RequestParamsDto paramsDto) {
        SearchParamsDto dto = new SearchParamsDto();

        // 查询应用搜索配置
        List<SysSheetSearchVo> searchList = sheetSearchMapper.selectVoList(
            new LambdaQueryWrapper<SysSheetSearch>().eq(SysSheetSearch::getSheetId, paramsDto.getSheetId())
                .eq(SysSheetSearch::getStatus,YesOrNoEnum.YES.getCode())

        );

        // 输入框数据
        StringBuilder inputSb = new StringBuilder();
        // 时间查询
        StringBuilder timeSb = new StringBuilder();
        // 时间区间
        StringBuilder timeBetweenSb = new StringBuilder();
        // 自定义数据源下拉选项
        List<Map<String,Object>> selectSearchMap = new ArrayList<>();

        // 查询组装
        searchList.forEach(search -> {
            paramsDto.getFieldList().forEach(field -> {

                if (search.getSheetSearchId().equals(field.getFieldId()) && StringUtils.isNotEmpty(field.getSearchValue())){
                    // 下拉项
                    if (SearchTypeEnum.getSelectType().contains(search.getSearchType())){
                        Map<String,Object> fieldMap = new HashMap<>();
                        fieldMap.put("fieldId", search.getSearchFieldId());
                        fieldMap.put("value", field.getSearchValue());
                        fieldMap.put("searchType", search.getSearchType());
                        selectSearchMap.add(fieldMap);
                    }  else if (search.getSearchType().equals(SearchTypeEnum.INPUT.getSearchType())){
                        // 普通输入框
                        String[] searchField = search.getSearchFieldName().split(SplitType.SPLIT_COMMA);
                        inputSb.append("(");
                        for (String str : searchField) {
                            inputSb.append("t.").append(str).append(" like CONCAT('%', '").append(field.getSearchValue()).append("','%') ");
                            if (search.getCheckType() != null) {
                                inputSb.append(search.getCheckType()).append(" ");
                            }
                        }
                        if (search.getCheckType() != null){
                            int index = inputSb.lastIndexOf(search.getCheckType());
                            inputSb.delete(index, index+2);
                        }

                        inputSb.append(")");
                    } else if (search.getSearchType().equals(SearchTypeEnum.DATE.getSearchType())){
                        // 时间筛选
                        timeSb.append("t.").append(search.getSearchFieldName());
                        String checkType = search.getCheckType() == null ? "=" : search.getCheckType();
                        timeSb.append(checkType).append("'").append(field.getSearchValue()).append("'");

                    } else if (search.getSearchType().equals(SearchTypeEnum.BETWEEN_DATE.getSearchType())){
                        // 时间区间
                        String[] sting = field.getSearchValue().split(SplitType.SPLIT_COMMA);
                        timeBetweenSb.append("t.").append(search.getSearchFieldName());
                        String checkType = search.getCheckType() == null ? "between" : search.getCheckType();
                        timeBetweenSb.append(" ").append(checkType).append(" '").append(sting[0]).append("' and '").append(sting[1]).append("'");
                    }
                }
            });
        });

        List<String> list = new ArrayList<>();
        list.add(inputSb.toString());
        list.add(timeSb.toString());
        list.add(timeBetweenSb.toString());

        String inputParams = list.stream().filter(StringUtils::isNotEmpty).collect(Collectors.joining(" and "));

        dto.setInputParams(inputParams);
        dto.setSelectParams(selectSearchMap);
        return dto;
    }

    /**
     * 批量删除平台通用列表（逻辑删除）
     * @param ids
     * @param sheetId
     * @return
     */
    @Override
    public int deleteByIds(String ids, Long sheetId) {
        SysSheet sheetVo = sheetMapper.selectById(sheetId);
        if (sheetVo != null){
            DelParamsDto dto = new DelParamsDto();
            dto.setTenantId(sheetVo.getTenantId());
            dto.setTableName(sheetVo.getTableName());
            dto.setDelField(sheetVo.getTableId());
            dto.setDelValue(Arrays.asList(ids.split(SplitType.SPLIT_COMMA)));
            dto.setUpdateBy(LoginHelper.getUserId());
            dto.setUpdateTime(new Date());
            return platformListMapper.deleteByIds(dto);
        }
        return 0;
    }

}
